/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package gfs.board;

import gfs.location.Location;
import java.util.ArrayList;

/**
 * General implementation of the interface Board without the method @link 
 * gfs.Board#getMoveLocations() because of the nature of the method it does not
 * allow for a general implementation as it may vary greatly from Board to Board
 * 
 * @author Joel
 */
public abstract class AbstractBoard implements Board
    {
    /** The underlying 2D array that functions as a board to contain objects on*/
    protected Object[][] map;

    protected AbstractBoard(Object[][] map) 
        {
        this.map = map;
        }        
    
    /**
     * Returns a shadow clone of this board's map
     * 
     * @return
     *      A shallow clone of this board's map
     */
    public Object[][] getMap() 
        {
        return map.clone();
        }

    /**
     * Returns the object at location loc
     * 
     * @param loc
     *      The location from which to get the object at
     * @return
     *      The object at the location or null if the location is not valid 
     */
    public Object get(Location loc) 
        {
        Object obj = null;
        if(isValid(loc))
            obj = map[loc.getRow()][loc.getCol()];            
        return obj;
        }       

    /**
     * Checks if a location in this board is valid or not
     * 
     * @param loc
     *      The location to test if it is valid
     * @return
     *      true if the location is valid in this board else false
     */
    public boolean isValid(Location loc) 
        {
        boolean bool = true;
        if(loc == null)
            return false;
        if(loc.getRow() < 0 || loc.getRow() > map.length)
            bool = false;
        if(loc.getCol() < 0 || loc.getCol() > map[loc.getRow()].length)
            bool = false;
        return bool;
        }

    /**
     * Removes the object at the given location in this board
     * 
     * @param loc
     *      The location from which an object is to be removed
     * @return
     *      The object that was removed or null if the location is not valid in 
     * this board
     */
    public Object remove(Location loc) 
        {
        Object obj = null;
        if(isValid(loc))
            {
            obj = map[loc.getRow()][loc.getCol()];
            map[loc.getRow()][loc.getCol()] = null;
            }
        return obj;
        }
        
    /**
     * Sets an object at the given location 
     * 
     * @param obj
     *      The object to set
     * @param loc
     *      The location to set the object at
     * @return
     *      true if the object was set else false
     */
    public boolean set(Object obj, Location loc) 
        {
        if(obj == null)
            return false;
        if(!isValid(loc) || check(loc))
            return false;
        else
            map[loc.getRow()][loc.getCol()] = obj;
        return true;
        }
    
    /**
     * Returns a boolean telling you if their is an object at Location loc
     * 
     * @param loc
     *      The Location to "check" at to see if it contains an object
     * @return
     *      <tt>true</tt> if there is an object else false
     */
    public boolean check(Location loc)
        {
        return get(loc) != null;
        }

    /**
     * Returns the locations adjacent to the location loc
     * 
     * @param loc
     *      The loc to get the adjacent loctions to
     * @return
     *      An ArrayList of all adjacent locations to the specified one. <tt>null
     * </tt> if the location is not valid in this board
     */
    public ArrayList<Location> getAdjacentLocations(Location loc) 
        {
        ArrayList<Location> locs = null;
        if(isValid(loc))
            {
            int initRow = loc.getRow() - 1;
            int initCol = loc.getCol() - 1;
            for(int x = 0; x < 9; initRow++, initCol++)
                {
                Location lc = new Location(initRow, initCol,10);
                if(isValid(lc) && !loc.equals(lc))
                    locs.add(lc);
                }
            }
        return locs;
        }
    
    }
